﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting.Compact;
using Serilog.Sinks.Grafana.Loki;
using Serilog.Sinks.OpenTelemetry;
using Service.Core.Serilog.Configuration;
using Service.Core.Serilog.Extensions;
using Service.Core.Serilog.Utility;
using Service.Framework;
using Service.Framework.Utils;

namespace Service.Core.Serilog
{
    public static class ServiceSerilogExtensions
    {
        public static void AddSerilogService(this WebApplicationBuilder builder)
        {

            AppSettings<SerilogConfigure> appSettings = builder.Services.BuildServiceProvider().GetRequiredService<AppSettings<SerilogConfigure>>();
            var loggerConfiguration = new LoggerConfiguration()
                .ReadFrom.Configuration(builder.Configuration)
                .Enrich.FromLogContext()
                .Enrich.WithThreadId()
                .Enrich.WithProperty("App", Tools.GetAppName(builder.Environment.ApplicationName)) // 全局固定属性
                .Enrich.WithProperty("Env", builder.Environment.EnvironmentName)
                //输出到控制台
                .WriteToConsole()
                //将日志保存到文件中
                .WriteToFile()
                //配置日志库
                .WriteToLogBatching();


            if (appSettings?.Instance.Seq != null)
            {
                var address = appSettings?.Instance.Seq.ServerUrl;
                var apiKey = appSettings.Instance.Seq.ApiKey;
                if (!string.IsNullOrWhiteSpace(address))
                {
                    loggerConfiguration =
                        loggerConfiguration.WriteTo.Seq(address, restrictedToMinimumLevel: LogEventLevel.Information,
                            apiKey: apiKey, eventBodyLimitBytes: 10485760, payloadFormatter: new CompactJsonFormatter());
                }
            }
            if (appSettings?.Instance.OpenTelemetry != null)
            {
                loggerConfiguration.WriteTo.OpenTelemetry(options =>
                {
                    options.Endpoint = appSettings?.Instance.OpenTelemetry.Endpoint;
                    options.Protocol = OtlpProtocol.Grpc;
                });
            }

            if (!string.IsNullOrWhiteSpace(appSettings?.Instance.GrafanaLokiUrl))
            {
                loggerConfiguration.WriteTo.GrafanaLoki(
                       appSettings?.Instance.GrafanaLokiUrl,
                     labels: new List<LokiLabel> {

                            new() { Key = "app", Value = Tools.GetAppName(builder.Environment.ApplicationName) },
                            new() { Key = "env", Value = builder.Environment.EnvironmentName },
                     },
                     textFormatter: new CompactJsonFormatter()
                );
            }

            Log.Logger = loggerConfiguration.CreateLogger();
            //LogContext.PushProperty(LogPaths.LogSource, LogPaths.AopSql);
            //LogContext.PushProperty(LogPaths.SqlOutToFile, true);
            //LogContext.PushProperty(LogPaths.SqlOutToConsole, true);
            //Serilog 内部日志
            var file = File.CreateText(LogPaths.Combine($"SerilogDebug{DateTime.Now:yyyyMMdd}.txt"));
            SelfLog.Enable(TextWriter.Synchronized(file));
            builder.Host.UseSerilog();
        }

        /// <summary>
        /// 添加Serilog中间件
        /// </summary>
        /// <param name="webApplication"></param>
        public static void AddSerilogConfigure(this WebApplication webApplication)
        {
            webApplication.UseSerilogRequestLogging(options =>
            {
                options.MessageTemplate = SerilogRequestUtility.HttpMessageTemplate;
                options.GetLevel = SerilogRequestUtility.GetRequestLevel;
                options.EnrichDiagnosticContext = SerilogRequestUtility.EnrichFromRequest;
            });

        }
    }
}
